﻿using System.Collections.Generic;
using System.Linq.Expressions;
using MyBasicLib.Extensions;
using MyBasicLib.Collections.Generic;

namespace MyBasicLib.Data.ORMLiteNew.Translation
{
    internal class TableKey
    {
        public string Type { get; set; }
        public string ArgName { get; set; }
        // public bool join { get; set; }
        public override string ToString()
        {
            return Type + ArgName; // +join;
        }
    }

    public class TableAliasCache
    {
        private readonly ICache<string, string> cacheName = new SimpleCache<string, string>();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="exp"></param> 
        /// <remarks>
        /// p=>p.p
        /// p=>p.Id
        /// p=>p.t.Id
        /// p.Id
        /// p.t.Id
        /// p.t
        /// </remarks>
        /// <returns> 
        /// </returns>
        public string GetTableAlias(Expression exp)
        {
            Check.Argument.IsNotNull(exp, "exp");
            TableKey key = GetTableAliasKey(exp);
            return cacheName.FetchOrCreateItem(key.ArgName, p => "t" + cacheName.Count);
            //if (!cacheName.ContainsKey(key.ArgName))
            //{
            //    cacheName[key.ArgName] = "t" + cacheName.Count;
            //}
            //return cacheName[key.ArgName];
        }

        private static TableKey GetTableAliasKey(Expression exp)
        {
            MemberExpression mp;
            var key = new TableKey();
            var pe = exp as ParameterExpression;
            if (pe != null)
            {
                key.Type = pe.Type.Name;
                key.ArgName = pe.Name;
                return key;
            }
            var lmd = exp as LambdaExpression;
            if (lmd != null)
            {
                mp = lmd.Body as MemberExpression;
                if (mp == null) //p=>p
                {
                    key.Type = (lmd.Body as ParameterExpression).Type.Name;
                    key.ArgName = (lmd.Body as ParameterExpression).Name;
                    return key;
                }
            }
            else
            {
                mp = exp as MemberExpression;
            }
            if (mp == null)
            {
                return key;
            }
            if (MetaData.IsValidTableClass(mp.Type))
            {
                key.Type = mp.Type.Name;
                key.ArgName = mp.Member.Name;
                return key;
            }
            Expression newExpression = mp.Expression.TrimUnary();
            if (MetaData.IsValidTableClass(newExpression.Type))
            {
                key.Type = newExpression.Type.Name;
                pe = newExpression as ParameterExpression;
                if (pe != null)
                {
                    key.ArgName = pe.Name;
                    return key;
                }
                return GetTableAliasKey(newExpression);
            }
            mp = mp.Expression as MemberExpression;
            if (mp != null)
                if (MetaData.IsValidTableClass(mp.Expression.Type))
                {
                    key.Type = mp.Expression.Type.Name;
                    key.ArgName = mp.Member.Name;
                    return GetTableAliasKey(newExpression);
                }

            return key;
        }

        //Dictionary<string, string> cacheType = new Dictionary<string, string>();
        //List<TableKey> cacheKey = new List<TableKey>();
        //List<string> cacheSameType = new List<string>();


        //[Obsolete]
        //public string GetTableAlias(Expression exp, bool join)
        //{

        //    var key = GetTableAliasKey(exp);

        //    var ali = "";
        //    ali = "t" + cacheKey.Count;
        //    cacheKey.Add(key);
        //    if (join)
        //    {
        //        if (cacheType.ContainsKey(key.Type))     //同表
        //        {
        //            cacheName[key.ArgName] = ali;
        //            var oldkey = cacheKey.SingleOrDefault(p => p.Type == key.Type && p.ArgName != key.ArgName);
        //            var oldali = cacheType[oldkey.Type];
        //            cacheName[oldkey.ArgName] = oldali;
        //            cacheType.Remove(oldkey.Type);
        //            cacheSameType.Add(key.Type);
        //            //cacheType[key.Type] = ali;

        //        }
        //        else if (cacheSameType.Contains(key.Type)) {//同表

        //            cacheName[key.ArgName] = ali;
        //        }
        //        else
        //        {

        //            cacheType[key.Type] = ali;

        //        }
        //    }
        //    else
        //    {
        //        if (cacheType.ContainsKey(key.Type))
        //        {
        //            return cacheType[key.Type];
        //        }
        //        else if (cacheName.ContainsKey(key.ArgName))
        //        {

        //            return cacheName[key.ArgName];
        //        }


        //        // if (!join)
        //       // {//不需要添加
        //            return "t0";
        //       // }
        //        // ali = "t" + cache.Count;
        //        // cache[key] = ali;
        //    }
        //    return ali;
        //}
        //public string GetTableAlias(string parName)
        //{
        //    var key = parName;// +exp.ToString();
        //    var ali = "";
        //    if (cache.ContainsKey(key))
        //    {
        //        ali = cache[key];
        //    }
        //    else
        //    {
        //        ali = "t" + cache.Count;
        //        cache[key] = ali;
        //    }
        //    return ali;
        //}
    }
}